﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Input;
using Bling.Core;
using Bling.WPF;
using Bling.WPF.Util;
using Bling.Slides;
using Bling.Util;
using Bling.Shaders;
using Bling.Graphics;

namespace Bling.TestP {
  using Bling.Shapes;
  using Bling.WPF.Custom;
  public class BezierTest : Canvas {
    public BezierTest() {
      var Self = this.Bl();
      var r = new Random();
      var red = new ThumbBl(Self) {
        Background = Brushes.Red, Size = 10, CanDrag = true, CenterPosition = r * Self.Size,
      };
      var blue = new ThumbBl(Self) {
        Background = Brushes.Blue, Size = 20, CanDrag = true, CenterPosition = r * Self.Size, ZIndex = 1,
      };
      var green = new ThumbBl(Self) {
        Background = Brushes.Green, Size = 20, CanDrag = true, CenterPosition = r * Self.Size, ZIndex = 1,
      };
      var purple = new ThumbBl(Self) {
        Background = Brushes.Purple, Size = 10, CanDrag = true, CenterPosition = r * Self.Size,
      };
      var t0 = new SliderBl(Self) {
        LeftTop = 0,
        Minimum = 0, Value = 0.25, Width = Self.Width,
      };
      var t1 = new SliderBl(Self) {
        LeftTop = t0.LeftBottom,
        Minimum = t0.Value, Maximum = 1, Value = 0.75, Width = Self.Width,
      };
      t0.Maximum = t1.Value;

      var lbl0 = new LabelBl(Self) {
        LeftTop = t1.LeftBottom,
        Font = { Weight = FontWeights.SemiBold, Size = 30, Family = "Courier New".Convert<FontFamily>() },
        Content = t0.Value.ToStringBl(100d) + ".Bezier(1, points).Bind = blue (" + blue.CenterPosition.ToStringBl(1d) + ")",
      };
      var lbl1 = new LabelBl(Self) {
        LeftTop = lbl0.LeftBottom,
        Font = lbl0.Font,
        Content = t1.Value.ToStringBl(100d) + ".Bezier(2, points).Bind = green (" + green.CenterPosition.ToStringBl(1d) + ")",
      };


      var segment = new BezierSegmentBl() {
        Point3 = purple,
      };
      new ThumbBl(Self) {
        Background = Brushes.Blue, Size = 10, CenterPosition = segment.Point1,
      };
      new ThumbBl(Self) {
        Background = Brushes.Green, Size = 10, CenterPosition = segment.Point2,
      };

      var points = segment.Points(red);
      t0.Value.Bezier(1, points).Bind = blue;
      t1.Value.Bezier(2, points).Bind = green;

      var shape = new PathShapeBl(Self) {
        Stroke = { Thickness = 2, Brush = Brushes.Black },
        Start = red, IsHitTestVisible = false,
      };
      shape.Segments.Add(segment);
      var shape2 = new PathShapeBl(Self) {
        Stroke = { Thickness = 1, Brush = Brushes.Black },
        Start = red, 
        Segments = {
          AddMany = new PathSegmentBl[] {
            segment.Point1, segment.Point2, segment.Point3
          },
        }, IsHitTestVisible = false,
      };


    }

  }

  public class Foo : Canvas {
    public Foo() {
      var Self = this.Bl();
      var sliderA = new SliderBl(Self) { Width = Self.Width, LeftTop = 0d, Minimum = 0, Maximum = 2 };
      var sliderB = new SliderBl(Self) { Width = Self.Width, LeftTop = sliderA.LeftBottom, Minimum = 0, Maximum = 1 };
      var sliderC = new SliderBl(Self) { Width = Self.Width, LeftTop = sliderB.LeftBottom, Minimum = 0, Maximum = 1 };
      var v = this.Property(sliderA.Value > 1).Condition(sliderB, sliderC).Value;
      v = this.Property(v);
      //(sliderA.Value + sliderB.Value).TwoWay = sliderC.Value;
      var label = new LabelBl(Self) {
        LeftTop = sliderC.LeftBottom,
        Content = v.ToStringBl(),
      };
      var b = new ButtonBl(Self) {
        LeftTop = label.RightTop,
        Content = "Animate",
      };
      sliderA.Value[b.Click1].Animate().StopOnCompleted(true).To = 2d;

      var rect = new RectangleBl(this) {
        Fill = Brushes.Red, Size = 300, CenterPosition = this.Bl().CenterSize,
        ZIndex = 1,
      };
      var rect0 = new RectangleBl(this) {
        Fill = Brushes.Black,
        Size = rect.Size + 20,
        CenterPosition = rect.CenterPosition,
        ZIndex = 0,
      };
      rect0.Visibility = rect.Mouse.ToBool;

      rect.Mouse.HoldTimeout = TimeSpan.FromMilliseconds(300);
      var p = this.Property(Double2Bl.Zero);
      FrameworkElementBl Next;
      Next = new LabelBl(this) {
        RightBottom = this.Bl().Size,
        Content = "Answer ".Bl() + p,
      };
      var Next0 = new ButtonBl(this) {
        LeftBottom = new Double2Bl(0, this.Bl().Height),
        Content = "MouseMove",
      };
      Next = Next0;
      p[Next0.Click1].Bind = rect.Mouse.Position;

      var StopTap = rect.Mouse.Click.SubscribeForever(() => Console.WriteLine("TAPPED"));
      Next = new ButtonBl(this) {
        LeftBottom = Next.RightBottom,
        Content = "Nothing",
        Click = () => {
          p.Bind = 0d;
          StopTap();
        }
      };
      Next = new LabelBl(this) {
        LeftBottom = Next.RightBottom,
        Content = "Drag",
        Foreground = rect.Mouse.Drag.ToBool.Condition(Brushes.Red.Bl(), Brushes.Black),
      };
      Next = new LabelBl(this) {
        LeftBottom = Next.RightBottom,
        Content = "Captured",
        Foreground = rect.Mouse.Capture.Has.Condition(Brushes.Red.Bl(), Brushes.Black),
      };
      var q = this.Property(Double2Bl.Zero);

      q[rect.Mouse.Hold.Update] = q[rect.Mouse.Hold.In] + (rect.Mouse.Position - rect.Mouse.Position[rect.Mouse.Hold.In]);
      Next = new LabelBl(this) {
        LeftBottom = Next.RightBottom,
        Content = "Hold ".Bl() + q.ToStringBl(100d),
        Foreground = rect.Mouse.Hold.ToBool.Condition(Brushes.Red.Bl(), Brushes.Black),
      };
      Next = new LabelBl(this) {
        LeftBottom = Next.RightBottom,
        Content = "Space",
        Foreground = rect.Keys[Key.Space].Condition(Brushes.Red.Bl(), Brushes.Black),
      };

      // acquire keyboard focus.
      {
        rect.Keys.Focus.Enabled = true;
        rect.Keys.Focus.Acquire[rect.Loaded].Apply();
        var KeyNow0 = rect.Keys.Target.Clamp(Key.A, Key.Z) - Key.A;
        rect.Fill[rect.Keys.Down] = KeyNow0.SelectColor();
      }
      rect.Fill.Changed.SubscribeForever(() => Console.WriteLine("FILL CHANGED: " + rect.Fill.CurrentValue));
    }

  }
}

namespace Bling.Tutorial {
  public class Driver : SlideHolder {
    public Driver() {
      this["Cube"] = () => new CubeTest2();
      //this["Foo"] = () => new Bling.TestP.Foo();
      //this["Layout"] = () => new CustomLayout();

      this["Title"] = () => new Title();
      this["Constraints"] = () => new Constraints();
      this["Pie"] = () => new PieTest();
      this["Shaders"] = () => new Shaders();
      this["MetaBall"] = () => new MetaBall();
      this["Lighting"] = () => new LightingExample();
      this["Web Browser"] = () => new BrowserTest();
      this["Physics"] = () => new PhysicsShape();
      this["Sphere3D"] = () => new VirtualSphereTest();
      this["WPF3D"] = () => new WPF3DTest();
      this["Transitions"] = () => new TransitionsTest();
      this["Ripple"] = () => new RipplesTest();
      this["Tweens"] = () => new Tweens();
      this["Menus"] = () => new Menus();

      this["Matrix"] = () => new MatrixTest();
      this["Angles"] = () => new AngleTest();
      this["Curves"] = () => new CurveTest();


      this["Tables"] = () => new Tables();
    }
    [STAThread]
    public static void Main(string[] args) {
      var win = new Window() { Title = "Bling Tutorial", Content = new Driver() };
      new Application().Run(win);
      return;
    }
  }
  public class Title : Canvas, ICanStart {
    private readonly LabelBl title;
    public static readonly ImageBrushBl Autumn = new ImageBrush(new BitmapImage("Resources/Autumn.jpg".MakePackUri(typeof(RipplesTest)))); 
    /*
    public static readonly GetProperty<Title, double> AnimateProperty = "Animate".NewProperty<Title, double>();
    public DoubleBl Animate {
      get { return AnimateProperty[this]; }
      set { Animate.Bind = value; }
    }*/
    private readonly DoubleBl Animate;
    public Title() {
      CanvasBl MainCanvas = this.Bl();


      Animate = this.Property(DoubleBl.Default);
      title = new LabelBl(this) {
        Font = { Size = 120, Weight = FontWeights.SemiBold, },
        CenterPosition = this.Bl().CenterSize,
        Content = "Bling Tutorial".Bl(),
        //RenderTransform = { Rotate = 45.ToDegrees() * -1d + 90.ToDegrees() * Animate * Animate * Animate },
      };
      Tex2D noise = 0.5.Bl().Lerp<Tex2D>((Tex2D) ShaderLib.Noise, (Tex2D) Autumn);
      title.Effect.Custom = (input,uv) => {
        var uv0 = new Double2Bl((uv.X + 13d * Animate), (uv.Y + 17d * Animate)) % 1d;
        return new ColorBl(noise[uv0].ScRGB, input[uv].ScA);
      };

      return;
    }
    public void Start() {
      Animate.Animate().Forever().AutoReverse().To = 1;
    }
    public void Stop() {
      Animate.Stop(false);
    }
  }
}
